package cn.iocoder.yudao.module.project.service.internalworkstationplan;

import cn.iocoder.yudao.module.project.dal.dataobject.internalcode.InternalCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.workstation.WorkstationDO;
import cn.iocoder.yudao.module.project.dal.mysql.internalcode.InternalCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.workstation.WorkstationMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.project.controller.admin.internalworkstationplan.vo.*;
import cn.iocoder.yudao.module.project.dal.dataobject.internalworkstationplan.InternalWorkstationPlanDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.project.dal.mysql.internalworkstationplan.InternalWorkstationPlanMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.project.enums.ErrorCodeConstants.*;

/**
 * 内码工位计划 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class InternalWorkstationPlanServiceImpl implements InternalWorkstationPlanService {

    @Resource
    private InternalWorkstationPlanMapper internalWorkstationPlanMapper;

    @Resource
    private WorkstationMapper workstationMapper;

    @Resource
    private InternalCodeMapper internalCodeMapper;

    @Override
    public String createInternalWorkstationPlan(InternalWorkstationPlanSaveReqVO createReqVO) {
        // 插入
        InternalWorkstationPlanDO internalWorkstationPlan = BeanUtils.toBean(createReqVO, InternalWorkstationPlanDO.class);
        internalWorkstationPlanMapper.insert(internalWorkstationPlan);
        // 返回
        return internalWorkstationPlan.getId();
    }

    @Override
    public void updateInternalWorkstationPlan(InternalWorkstationPlanSaveReqVO updateReqVO) {
        // 校验存在
        validateInternalWorkstationPlanExists(updateReqVO.getId());
        // 更新
        InternalWorkstationPlanDO updateObj = BeanUtils.toBean(updateReqVO, InternalWorkstationPlanDO.class);
        internalWorkstationPlanMapper.updateById(updateObj);
    }

    @Override
    public void deleteInternalWorkstationPlan(String id) {
        // 校验存在
        validateInternalWorkstationPlanExists(id);
        // 删除
        internalWorkstationPlanMapper.deleteById(id);
    }

    private void validateInternalWorkstationPlanExists(String id) {
        if (internalWorkstationPlanMapper.selectById(id) == null) {
            throw exception(INTERNAL_WORKSTATION_PLAN_NOT_EXISTS);
        }
    }

    @Override
    public InternalWorkstationPlanDO getInternalWorkstationPlan(String id) {
        return internalWorkstationPlanMapper.selectById(id);
    }

    @Override
    public PageResult<InternalWorkstationPlanDO> getInternalWorkstationPlanPage(InternalWorkstationPlanPageReqVO pageReqVO) {
        return internalWorkstationPlanMapper.selectPage(pageReqVO);
    }

    @Override
    @Transactional
    public void createInternalWorkstationPlan(String internalCode) {
        List<WorkstationDO> workstationDOList = workstationMapper.selectList();

        List<InternalWorkstationPlanDO> internalWorkstationPlanDOList = new ArrayList<>();

        InternalCodeDO internalCodeDO = internalCodeMapper.selectById(internalCode);

        for(WorkstationDO workstationDO : workstationDOList){
            InternalWorkstationPlanDO internalWorkstationPlanDO = new InternalWorkstationPlanDO();
            internalWorkstationPlanDO.setId(UUID.randomUUID().toString());
            internalWorkstationPlanDO.setInternalCode(internalCode);
            internalWorkstationPlanDO.setWorkstationId(workstationDO.getId());
            internalWorkstationPlanDO.setCompletedStatus(0);
            internalWorkstationPlanDO.setOrderCode(internalCodeDO.getOrderCode());
            internalWorkstationPlanDOList.add(internalWorkstationPlanDO);
        }
        internalWorkstationPlanMapper.insertBatch(internalWorkstationPlanDOList);
    }

    @Override
    @Transactional
    public void completeWorkstationPlan(String internalCode, Integer workstationId) {
        QueryWrapper<InternalWorkstationPlanDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("internal_code", internalCode);
        queryWrapper.eq("workstation_id", workstationId);
        queryWrapper.eq("completed_status", 0);

        InternalWorkstationPlanDO internalWorkstationPlanDO = internalWorkstationPlanMapper.selectOne(queryWrapper);

        if(internalWorkstationPlanDO == null){
            return;
        }

        if(internalWorkstationPlanDO.getCompletedStatus().intValue() == 1){
            return;
        }

        InternalWorkstationPlanDO updateInternalWorkstationPlanDO = new InternalWorkstationPlanDO();
        updateInternalWorkstationPlanDO.setCompletedStatus(1);
        updateInternalWorkstationPlanDO.setId(internalWorkstationPlanDO.getId());
        internalWorkstationPlanMapper.updateById(updateInternalWorkstationPlanDO);
    }


    @Override
    public void checkAndCompletePlan(String orderCode){
        List<InternalCodeDO> internalCodeDOList = internalCodeMapper.selectList(InternalCodeDO::getOrderCode, orderCode);

        List<String> internalCodeIdList = internalCodeDOList.stream().map(internalCodeDO -> internalCodeDO.getId()).collect(Collectors.toList());

        List<WorkstationDO> workstationDOList = workstationMapper.selectList();
        int workstationCount = workstationDOList.size();

        List<Integer> fullWorkstationIdList = workstationDOList.stream().map(workstationDO -> workstationDO.getId()).collect(Collectors.toList());

        for(String internalCode : internalCodeIdList){
            List<InternalWorkstationPlanDO> internalWorkstationPlanDOList = internalWorkstationPlanMapper.selectList(InternalWorkstationPlanDO::getInternalCode, internalCode);

            if(internalWorkstationPlanDOList.size() == workstationCount){
                continue;
            }

            List<Integer> workstationIdList = internalWorkstationPlanDOList.stream().map(internalWorkstationPlanDO -> internalWorkstationPlanDO.getWorkstationId()).collect(Collectors.toList());

            List<Integer> notExistWorkstationIdList = fullWorkstationIdList.stream().filter(workstationId -> !workstationIdList.contains(workstationId)).collect(Collectors.toList());

            createInternalWorkstationPlan(internalCode, notExistWorkstationIdList);
        }

    }

    @Transactional
    public void createInternalWorkstationPlan(String internalCode, List<Integer> workstationIdList) {
        List<WorkstationDO> workstationDOList = workstationMapper.selectList(WorkstationDO::getId, workstationIdList);

        List<InternalWorkstationPlanDO> internalWorkstationPlanDOList = new ArrayList<>();

        InternalCodeDO internalCodeDO = internalCodeMapper.selectById(internalCode);

        for(WorkstationDO workstationDO : workstationDOList){
            InternalWorkstationPlanDO internalWorkstationPlanDO = new InternalWorkstationPlanDO();
            internalWorkstationPlanDO.setId(UUID.randomUUID().toString());
            internalWorkstationPlanDO.setInternalCode(internalCode);
            internalWorkstationPlanDO.setWorkstationId(workstationDO.getId());
            internalWorkstationPlanDO.setCompletedStatus(0);
            internalWorkstationPlanDO.setOrderCode(internalCodeDO.getOrderCode());
            internalWorkstationPlanDOList.add(internalWorkstationPlanDO);
        }
        internalWorkstationPlanMapper.insertBatch(internalWorkstationPlanDOList);
    }

}